package cn.wuxing.mediation.businessplatform.factory;

import cn.hutool.core.util.ReflectUtil;
import cn.wuxing.mediation.businessplatform.domain.annotation.BusinessTag;
import cn.wuxing.mediation.common.exception.ServiceException;
import cn.wuxing.mediation.common.utils.DateUtils;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.reflections.Reflections;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 *@description:
 *@author:
 *@date 2023-09-05 15:30
 *@version: 1.0 <br>
 */
@SuppressWarnings("all")
@Slf4j
@Component
public class BusinessFactory implements ApplicationContextAware {


    private static ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BusinessFactory.applicationContext = applicationContext;
    }


    /**
     * 根据对应泛型创建子类实现
     *
     * @param t
     * @param v
     * @param <T>
     * @param <V>
     * @return
     * @throws Exception
     */
    public static <T> T doInstanceRealization(String type, Class<T> t) {

        List<Class<? extends T>> subClassList = getSubClassList(t);

        for (Class<? extends T> subClass : subClassList) {
            BusinessTag annotation = subClass.getAnnotation(BusinessTag.class);
            if (null == annotation) {
                continue;
            } else if (!type.equals(annotation.tag())) {
                continue;
            }

            return BusinessFactory.applicationContext.getBean(subClass);
        }

        throw new ServiceException("未找到该资源!");
    }


    public static <T> Class<?> doInstanceClass(String type, Class<T> t) throws Exception {

        Type genericSuperclass = doInstanceRealization(type, t).getClass().getGenericSuperclass();

        ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;

        Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];

        return Class.forName(actualTypeArgument.getTypeName());

    }

    /**
     * 根据下表获取泛型类型
     *
     * @param type
     * @param t
     * @param index
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> Class<?> doInstanceClass(String type, Class<T> t, Integer index) {

        try {

            for (Class<? extends T> subClass : getSubClassList(t)) {
                BusinessTag annotation = subClass.getAnnotation(BusinessTag.class);
                if (null == annotation) {
                    continue;
                } else if (!type.equals(annotation.tag())) {
                    continue;
                }

                ParameterizedType parameterizedType = (ParameterizedType) subClass.getGenericSuperclass();

                Type actualTypeArgument = parameterizedType.getActualTypeArguments()[index];

                return Class.forName(actualTypeArgument.getTypeName());
            }

        } catch (Exception e) {
            log.error("BusinessFactory [] doInstanceClass e :", e);

            throw new ServiceException("未找到该资源!");
        }

        throw new ServiceException("未找到该资源!");
    }


    /**
     * 根据下表获取泛型类型
     *
     * @param type
     * @param t
     * @param index
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> Class<?> doInstanceClass(Class<T> t, Integer index) {

        try {

            ParameterizedType parameterizedType = (ParameterizedType) t.getGenericSuperclass();

            Type actualTypeArgument = parameterizedType.getActualTypeArguments()[index];

            return Class.forName(actualTypeArgument.getTypeName());

        } catch (Exception e) {
            log.error("BusinessFactory [] doInstanceClass e :", e);

            throw new ServiceException("未找到该资源!");
        }

    }

    /**
     * 找到子类集合
     *
     * @param t
     * @param <T>
     * @return
     */
    private static <T> List<Class<? extends T>> getSubClassList(Class<T> t) {

        Reflections reflections = new Reflections(t.getPackage().getName());

        return new LinkedList<>(reflections.getSubTypesOf(t));

    }


    /**
     * 拼接
     *
     * @param index
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Class<? extends T> doInstanceAssembleClazz(String index, Class<T> t) {

        for (Class<? extends T> clazz : getSubClassList(t)) {
            if (!(index + t.getSimpleName()).equals(clazz.getSimpleName())) {
                continue;
            }

            return clazz;

        }

        return t;
    }


    /**
     * 获取参数
     *
     * @param type
     * @param t
     * @param index
     * @param request
     * @param <T>
     * @return
     */
    @SneakyThrows
    public static <T> T getInstanceField(String type, Class<?> t, Integer index, HttpServletRequest request) {
        Class<?> instanceClass = BusinessFactory.doInstanceClass(type, t, index);

        T newInstance = (T) instanceClass.newInstance();

        for (Field field : ReflectUtil.getFields(instanceClass)) {

            field.setAccessible(Boolean.TRUE);

            String parameter = request.getParameter(field.getName());

            if (null == parameter || parameter.isEmpty()) {
                continue;
            }

            field.set(newInstance, field.getType().equals(Date.class) ? DateUtils.convertStringToDate(parameter)
                    : ConvertUtils.convert(parameter, field.getType()));

        }

        return newInstance;
    }

}
